/**
* mainsvr 主逻辑
*/

#ifndef __MAINSVR_CTRL_H__
#define __MAINSVR_CTRL_H__


#include "maindef.h"
#include <sys/time.h>

#include "mainconfig.h"
#include "maindb.h"
#include "mainapi.h"
#include "commclass.h"
#include "CTMultiHashMgr.h"
#include "CDataUpdateMgr.h"

#include "PBMsgHead.pb.h"
#include "online/onlineuser.h"
#include "map/CMapView.h"
#include "maintask/CTaskMgr.h"
#include "data/CPlayerOnlineData.h"
#include "data/CRoleNameHash.h"
#include "equip/CEquipMgr.h"

#include "storage/CStorageMgr.h"
#include "item/CItemMgr.h"
#include "partner/CPartnerMgr.h"
#include "simpleconfig/CRoleConfigMgr.h"
#include "shop/CShopMgr.h"
#include "simpleconfig/CMonsterConfigMgr.h"
#include "instance/CInstanceMgr.h"
#include "skill/CSkillMgr.h"
#include "battle/CBattleMgr.h"
#include "role/CRoleMgr.h"
#include "matrix/CMatrixMgr.h"
#include "card/CCardMgr.h"
#include "soul/CSoulMgr.h"
#include "friend/CFriendMgr.h"
#include "garden/CGardenMgr.h"
#include "drug/CDrugMgr.h"
#include "arena/CArenaMgr.h"
#include "clan/CClanMgr.h"
#include "data/CZoneOnlineData.h"
#include "data/CPlayerCacheData.h"
#include "act/CActMgr.h"
#include "boss/CWorldBossMgr.h"
#include "status/CStatusMgr.h"
#include "scene/CSceneMgr.h"
#include "notify/CNotifyMgr.h"
#include "senwordpro.h"
#include "charsetconvert.h"
#include "lesson/CLessonMgr.h"
#include "energy/CEnergyMgr.h"
#include "dailytask/CDailyTaskMgr.h"
#include "treasure/CTreasureMgr.h"
#include "mainmemorydb.h"
#include "pet/CPetMgr.h"
#include "muse/CMuseMgr.h"
#include "mount/CMountMgr.h"
#include "fashion/CFashionMgr.h"
#include "simpleconfig/CCommConfigLoader.h"
#include "clan/CClanBattleMgr.h"
#include "clan/CClanTreeMgr.h"
#include "academy/CAcademyMgr.h"
#include "vip/CVipMgr.h"
#include "act/CEnemyActCityMgr.h"
#include "oss/COssMgr.h"
#include "gift/CGiftMgr.h"
#include "act/CMagicDoorMgr.h"
#include "act/CDiceMgr.h"
#include "act/CAuctionMgr.h"
#include "act/CWishMgr.h"
#include "act/CAcademyBossMgr.h"
#include "rank/CRankMgr.h"
#include "officegm/COfficeGMMgr.h"
#include "compass/CCompassMgr.h"
#include "qqmall/CQQMallMgr.h"
#include "act/CPyramidMgr.h"
#include "act/CDaySignMgr.h"
#include "act/CDayWishMgr.h"
#include "act/CNewbieTaskMgr.h"
#include "act/CFightEndMgr.h"
#include "act/CAcaCupMgr.h"
#include "chat/CChatMgr.h"
#include "market/CMarketMgr.h"
#include "fashion/CFashionMgr.h"
#include "act/CManorBattleMgr.h"
#include "act/CRewardBackMgr.h"
#include "act/CLoginRewardMgr.h"

#define CMainEpollObject CTEpollObject<CMainCtrl>

namespace __gnu_cxx
{
    template<> struct hash<CVarObjectKey>
    {
        size_t operator()(const CVarObjectKey& s) const
        {
            return ((__stl_hash_string(s.m_sStrID.Get())*214013)+
                ((CT_UINT64_LOW(s.m_u64ID)+CT_UINT64_HIGH(s.m_u64ID))* 214013 + 2531011)
                +s.m_chDataType)& 0x7FFFFFFF;
        }
    };

    typedef CTSizeString<USER_TOKEN_LEN> SZ_USER_TOKEN;
    template<> struct hash<SZ_USER_TOKEN>
    {
        size_t operator()(const SZ_USER_TOKEN& s) const
        {
            return __stl_hash_string(s.Get());
        }
    };
}

//存放hash共享内存结构的控制信息
class CShmCtrlInfo
{
public:
#define MAGICNUM_LEN 16

    static const unsigned char abyMagicNum[MAGICNUM_LEN];

    /* 该对象只会恢复共享内存中的数据或者设置新的数据
    CShmCtrlInfo()
    {
    m_iMemoryLen = 0;
    m_bInitFinished = false;
    }
    */

    inline bool CheckNeedReset(int iNowMenLen);

    //开始共享内存全部的初始化
    inline void StartFullInit(int iNowMenLen);

    //结束共享内存的初始化
    inline void EndFullInit();
private:
    //共享内存长度
    int m_iMemoryLen;

    //magic num
    unsigned char m_abyMagicNum[MAGICNUM_LEN];

    //共享内存初始化是否完成
    bool m_bInitFinished;
};

class MsgBattleResult;
class CMainCtrl
{
public:
    CMainCtrl();
    virtual ~CMainCtrl();

    int Init();
    int Run();
    int Exit();

    static void sigusr1_handle(int iSigVal);
    static void sigusr2_handle(int iSigVal);

    void OnShmQueueEvent(CMainEpollObject* pstObject, SOCKET iSocket, int iEvent);

    /**
    * 有些协议虽然合法, 但可能是内部协议, 不允许从client发过来
    */
    bool AuthClientMsg(const PBMsgHead& stMsgHead) const;

    //判断是否是管理端的消息
    bool FromAdmin(const CEnpNetHead& stHead);

    //返回请求
    int AnswerToClient(CEnpNetHead& stHead, CTBuffer& buff, bool bFlushBuf = false);

    void FlushSendCache();

    //maindb
    void HandleDBMsg(char* pszMsgBuf, int iMsgLen);
    int RequestToDB(const char* pszBuf, int iBufLen);

    //mainapi
    void HandleApiMsg(char* pszMsgBuf, int iMsgLen);
    int RequestToApi(const char* pszBuf, int iBufLen);

    //memory db
    int RequestToMemoryDB(const char* pszKey, int iKeyLen, const char* pszValue, int iValueLen, int iExestSecs);

    int RequestToMemoryDBWithPB(const char* pszKey, int iKeyLen, ::google::protobuf::Message& pbData, int iExestSecs);
    int BattleToMemoryDBWithPB(T_VIDEO_KEY& szVideoKey, unsigned int uiGID, int iVideoType, MsgBattleResult& stMsgBattleRes, int iExestSecs);

    template<typename KEY>
    static int GetDataFromUpdateMgr(KEY & stKey,char * szData, int iMaxSize, CVarObjectHead& stHead)
    {
        int iRet = CMainCtrl::m_pstMain->m_stUpdateMgr.GetData(stKey, szData, iMaxSize, stHead);
        if (iRet == 0) //找到数据
        {
            if(stHead.m_iDataInfo == VOP_DELETE)
            {
                CT_TRACE(("data was deleted"));
                return RET_DATA_DELETED;
            }
        }

        return iRet;
    }

    //用于编码PB的msghead
    int DecodePBMsg(::google::protobuf::Message& stMsgBody, void* pData, int iLength);
    int DecodePBMsg(::google::protobuf::Message& stMsgBody, CCmdPBDoParam* pstParam);
    int EncodePBMsg(::google::protobuf::Message& stMsgBody, CTBuffer& stBuff, bool bEncodeLen = true);
    int ReturnMsgHead(PBMsgHead& stMsgHead, CTLib::CEnpNetHead& stEnpHead);
    int ReturnMsgHead(unsigned int uiGID, int iCmd, int iRetValue);

    void DumpPBMsgToFile(const char* pszKey, ::google::protobuf::Message& pbData);

    template<typename T>
    static const char* DataEncode(T& stData, int& iLen)
    {
        iLen = 0;
        static char szDataBuf[CTMsgHead::EMAX_MSGLEN];
        CTBuffer stBuff;
        stBuff.Attach(szDataBuf,CTMsgHead::EMAX_MSGLEN,0);

        CTCodeStream s(stBuff);
        CodeConvert(s, stData, NULL, bin_encode());
        if (s.m_iRet != 0)
        {
            return NULL;
        }

        iLen = s.m_ushPos;
        return s.m_pszBuf;
    }

    template<typename T>
    static int DataDecode(T& stData, char* sBuf, int iLen)
    {
        if (sBuf == NULL || iLen > CTMsgHead::EMAX_MSGLEN || iLen <= 0)
        {
            return -1;
        }

        CTCodeStream s(sBuf, iLen);
        CodeConvert(s, stData, NULL, bin_decode());
        if (s.m_iRet != 0)
        {
            return -2;
        }

        return 0;
    }

    template<typename T>
    static void UpdateData(CVarObjectKey& stKey, T& stData, int iOpType)
    {
        BeforeUpdateData(stData);

        int iRet = 0;
        int iLen = 0;
        CT_TRACE(("update data , key1 = %s, key2 = %llu dataqtype %d", stKey.m_sStrID(), stKey.m_u64ID,stKey.m_chDataType));
        const char* sBuf = DataEncode(stData, iLen);
        if (NULL == sBuf)
        {
            CT_ERROR(("encode data error, key1 = %s, key2 = %llu", stKey.m_sStrID(), stKey.m_u64ID));
        }
        else
        {
            /*
            CVarObjectHead stNowHead;
            iRet = CMainCtrl::m_pstMain->m_stUpdateMgr.GetDataHead(stKey, stNowHead);
            if (iRet == RET_OK)
            {
                switch(stNowHead.m_iDataInfo)
                {
                case VOP_CREATE:
                    {
                        switch(iOpType)
                        {
                        case VOP_CREATE:
                            iOpType = VOP_CREATE;
                            break;
                        case VOP_UPDATE:
                            iOpType = VOP_CREATE;
                            break;
                        case VOP_DELETE:
                            CMainCtrl::m_pstMain->m_stUpdateMgr.DeleteData(stKey);
                            return 0;
                        default:
                            break;
                        }
                    }
                    break;
                case VOP_UPDATE:
                    {
                        switch(iOpType)
                        {
                        case VOP_CREATE:
                            iOpType = VOP_UPDATE;
                            break;
                        case VOP_UPDATE:
                            iOpType = VOP_UPDATE;
                            break;
                        case VOP_DELETE:
                            iOpType = VOP_DELETE;
                            break;
                        default:
                            break;
                        }
                    }
                    break;
                case VOP_DELETE:
                    {
                        switch(iOpType)
                        {
                        case VOP_CREATE:
                            iOpType = VOP_UPDATE;
                            break;
                        case VOP_UPDATE:
                            iOpType = VOP_UPDATE;
                            break;
                        case VOP_DELETE:
                            iOpType = VOP_DELETE;
                            break;
                        default:
                            break;
                        }
                    }
                    break;
                }
            }
            */

            CVarObjectHead stHead;
            stHead.m_iDataInfo = iOpType;
            stHead.m_iDataLen = iLen;
            iRet = CMainCtrl::m_pstMain->m_stUpdateMgr.UpdateData(stKey, sBuf, stHead);
            if (iRet != 0)
            {
                CT_ERROR(("update data error, key1 = %s, key2 = %llu", stKey.m_sStrID(), stKey.m_u64ID));
                CHECK_THROW(iRet);
            }

            CT_UPDATE(("+,%d,%d,%d,%s,%d", stKey.m_chDataType, CT_UINT64_HIGH(stKey.m_u64ID), CT_UINT64_LOW(stKey.m_u64ID), stKey.m_sStrID(), stHead.m_iDataInfo));
        }
    }

    template<typename T>
    static void BeforeUpdateData(T& stData)
    {
        return;
    }

    int CheckLogin(unsigned int uiGID, CEnpNetHead& stHead);
    int SetOnline(unsigned int uiGID, CEnpNetHead& stHead, CPlatformInfo& stPlatformInfo);
    int SetOffline(unsigned int uiGID, CEnpNetHead& stHead);
    int SetOfflineOnePlayer(unsigned int uiGID);
    int SetOfflineAllPlayer();

    //检查防沉迷
    void CheckDef();

    int NotifyOnlineUser(unsigned int uiGID, CTBuffer& stBuff);
    int NotifyOnlineUser(unsigned int uiGID, int iCmd, ::google::protobuf::Message& stMsgBody, bool bFlushData);
    int NotifyAllOnlineUser (CTBuffer& stBuff);

    int FindPlayerCacheData(unsigned int uiGID);

    int SendInnerCmd(unsigned int uiGID, int iCmd, ::google::protobuf::Message& stMsgReq, bool bNeedLogin);

    int SendInnerCmd (CTAsyncCmd* pstParent, unsigned int uiGID, int iCmd, ::google::protobuf::Message& stMsgReq, bool bNeedLogin);

    //int SendInnerCmd(unsigned int uiGID, int iCmd, CTSizeString<CSMsgDef::EMT_MAX_MSGLEN>& szMsgStr);

    int ZoneID() const
    {
        return CONF->ZoneID;
    }

    //世界等级
    int GetWorldLevel() const {return m_stArenaMgr._iWorldBossLevel;}

    //获取以来的天数. (开服当天返回1)
    int GetDaysSinceZoneOpen ();

    //发送tips
    void SendTips(unsigned int uiGID, CTips& stTips);
    void SendTips(unsigned int uiGID, COfflineTips& stOfflineTips);

    void SendOnlineTips(unsigned int uiGID, MsgTips & stTips);
    void SendOnlineTips(MsgTips& stTips);

    //帐号保活
    void TencentKeepLoginValid(int);

    bool IsTencentPlatform(const char* szPlatform);
    bool IsLocalPlatform(const char* szPlatform);

//#ifdef _DEBUG
private:
    unsigned int m_uiPkgKey;
    void ZeroPkgKey(){m_uiPkgKey = 0;}
    void AddPkgKey(){++m_uiPkgKey;}
    unsigned int GetPkgKey(){return m_uiPkgKey;}
//#endif

protected:
    void DumpStatInfo();

    /**
    * 处理来自客户端的消息
    */
    void HandleShmQueueMsg();

    //更新数据
    static int UpdateData(CVarObject * pstObj,CVarObjectKey * pstKey);

    //更新逻辑数据
    int UpdatePlayerBaseInfo(CPlayerBaseInfo& stPlayerBaseInfo);
    int CreatePlayerBaseInfo(CPlayerBaseInfo& stPlayerBaseInfo);

    //初始化数据
    int InitData();

    //换出数据，主要是hash
    void SwapData();

    //检查系统繁忙
    void CheckSysBusy();

    //处理HTTP请求
    void HandleHttpMsg(CEnpNetHead& stNetHead, const char* szMsg, unsigned short usMsgLen);

    //跨天处理
    void ProcWhenNewDayBegin (int iNowTime);

public:
    static CMainCtrl*       m_pstMain;
    bool                    m_bBeginRun;
    bool                    m_bResetShm;
    int                     m_iNow;         ///< 当前秒值
    int                     m_iDayZeroTime; ///< 当天0点时候的秒值
    CTBuffer                m_stEncodeBuf;  ///< 编码缓冲区
    CTBuffer                m_stDecodeBuf;  ///< 解码缓冲区
    //数据更新
    CUpdateDataMgr<CVarObjectKey>   m_stUpdateMgr;

public:
    static bool s_bReloadConfig;
    static bool s_bExit;

protected:
    CTEpoll                 m_stEpoll;
    CTShmQueue<CMainCtrl>   m_stShmQueue;

    CTShm                   m_stMgrShm;
    CTShm                   m_stUpdateMgrShm;

    CMainDB                 m_stDB;   /// 和dbsvr交互的对象
    CMainApi                m_stApi;   /// 和apisvr交互的对象

    CMainMemoryDB           m_stMemoryDB;   //内存数据库操作对象

    CTStat                  m_stStat;
    CTStat                  m_stCmdStat;

    char*                   m_szSendCache;
    CTBuffer                m_stSendCache;

public:
    struct tm               m_stTm;
    struct timeval          m_stNowTime;
    bool                    m_bDataIsInited;                                            //标识启动时数据是否已经初始化
    bool                    m_bIsSysBusy;                                               //标识系统繁忙
    bool                    m_bIsRunSlow;                                               //主循环是否执行缓慢

    CTArray<unsigned int, MAX_REGISTER_PLAYER> m_auiAllRegisterGID;
    CZoneOnlineData         m_stZoneOnlineData;                                         //大区全局数据

    CTHashObjectMgr<unsigned int, CPlayerBaseInfo>       m_stPlayerBaseInfoHash;        //用户基础信息数据
    CTHashObjectMgr<unsigned int, CPlayerDetailInfo>     m_stPlayerDetailInfoHash;      //用户详细信息数据
    CTHashObjectMgr<unsigned int, CPlayerDetailInfoEx1>  m_stPlayerDetailEx1InfoHash;   //用户详细信息扩展数据

    CTHashObjectMgr<unsigned int, CUnactPartnerInfo>     m_stUnactPartnerInfoHash;      //未激活伙伴列表
    CTHashObjectMgr<int, CInstanceZoneDetailInfo>        m_stInstanceZoneDetailInfoHash;//副本大区详细数据

    CTHashObjectMgr<CTSizeString<USER_TOKEN_LEN>, CGidList>   m_stUserTokenToGID;   //用户标识映射表

    CTHashObjectMgr<unsigned int, CPlayerSnsDetailInfo>     m_stPlayerSnsDetailInfoHash;    //用户社交信息详细数据
    CTHashObjectMgr<unsigned int, CPlayerSnsCommInfo>       m_stPlayerSnsCommInfoHash;      //用户社交信息数据，全cache，开机时需要初始化
    CTHashObjectMgr<unsigned int, CPlayerCacheData>         m_stPlayerCacheDataHash;        //用户全量Cache数据
    CRolenameHash                                           m_stRolenameHash;               //用于根据昵称找GID

    unsigned int            m_uiMaxGID;
    CPlayerOnline           m_stPlayerOnline;
    CMapViews               m_stMapViews;                                               //地图视野控制

    CUserDataInf            m_stTaskUserDataInf;                                        //任务数据访问接口
    CTaskMgr                m_stTaskMgr;                                                //任务控制器
    CEquipMgr               m_stEquipMgr;                                               //装备控制器
    CTHashObjectMgr<unsigned int, CPlayerOnlineData>      m_stPlayerOnlineDataHash;     //用户在线数据，不需要入库

    CStorageMgr             m_stStorageMgr;                                         //背包
    CItemMgr                m_stItemMgr;                                            //物品
    CPartnerMgr             m_stPartnerMgr;                                         //伙伴控制器
    CRoleMgr                m_stRoleMgr;                                            //主角控制器
    CRoleConfigMgr          m_stRoleConfigMgr;                                      //主角相关配置
    CShopMgr                m_stShopMgr;
    CMonsterConfigMgr       m_stMonsterConfigMgr;                                   //怪物配置
    CInstanceMgr            m_stInstanceMgr;                                        //副本控制器
    CSkillMgr               m_stSkillMgr;                                           //技能控制器
    CBattleMgr              m_stBattleMgr;                                          //战斗控制器
    CMatrixMgr              m_stMatrixMgr;                                          //阵形控制器
    CCardMgr                m_stCardMgr;                                            //卡片控制器
    CSoulMgr                m_stSoulMgr;                                            //魂器控制器
    CFriendMgr              m_stFriendMgr;                                          //好友控制器
    CGardenMgr              m_stGardenMgr;                                          //花园控制器
    CDrugMgr                m_stDrugMgr;                                            //魔药控制器
    CArenaMgr               m_stArenaMgr;                                           //竞技场控制器
    CActMgr                 m_stActMgr;                                             //活动控制器
    CWorldBossMgr           m_stWorldBossMgr;                                       //世界BOSS控制器
    CStatusMgr              m_stStatusMgr;                                          //角色状态控制器
    CSceneMgr               m_stSceneMgr;                                           //场景控制器
    CNotifyMgr              m_stNotifyMgr;                                          //用于主动进行用户数据下发
    CClanMgr                m_stClanMgr;                                            //家族控制器
    CMuseMgr                m_stMuseMgr;                                            //冥想控制器
    CMountMgr               m_stMountMgr;                                           //坐骑控制器
    CFashionMgr             m_stFashionMgr;                                         //时装控制器

    CSenWordPro             m_stSenWordMgr;                                         //sensitive word manager and query
    CCharSetConvert         m_stCharSetConvertMgr;                                  //字符集工具

    CLessonMgr              m_stLessonMgr;                                         //上课系统

    CSpecialAccountMgr      m_stSpecialAccountMgr;                                 //版署账号

    CEnergyMgr              m_stEnergyMgr;                                         //精力系统

    CDailyTaskMgr           m_stDailyTaskMgr;                                      //日常任务控制器
    CTreasureMgr            m_stTreasureMgr;                                       //秘宝控制器
    CPetMgr                 m_stPetMgr;                                            //宠物

    CCommConfigLoader       m_stCommConfigLoader;                                   //通用配置载入器

    CClanBattleMgr          m_stClanBattleMgr;                                      //家族战

    CAcademyMgr             m_stAcademyMgr;                                         //学院控制器
    CVipMgr                 m_stVipMgr;                                             //Vip控制器

    CEnemyAtkCityMgr        m_stEnemyAtkCityMgr;                                    //怪物攻城战

    CGiftMgr                m_stGiftMgr;                                            //礼包\奖励控制器
    COssMgr                 m_stOssMgr;                                             //OSS相关
    CMagicDoorMgr           m_stMagicDoorMgr;                                       //魔界门控制器

    CFamilyDiceMgr          m_stFamilyDiceMgr;                                  //家族闯关控制器
    CAuctionMgr             m_stAuctionMgr;                                     //拍卖会
    CClanTreeMgr            m_stTreeMgr;                                        //家族神树控制器
    CWishMgr                m_stWishMgr;                                        //许愿池
    CAcademyBossMgr         m_stAcademyBossMgr;                                 //学院BOSS控制器
    CRankMgr                m_stRankMgr;                                        //排行榜控制器
    COfficeGMMgr            m_stOfficeGMMgr;                                    //官方GM控制器

    CCompassMgr             m_stCompassMgr;                                     //腾讯罗盘接口

    CQQMallMgr              m_stQQMallMgr;                                      //腾讯商城
    CPyramidMgr             m_stPyramidMgr;                                     //金字塔活动
    CDaySignMgr             m_stDaySignMgr;                                     //每日签到控制器
    CDayWishMgr             m_stDayWishMgr;                                     //每日许愿控制器
    CNewbieTaskMgr          m_stNewbieTaskMgr;                                  //新手目标
    CFightEndMgr            m_stFightEndMgr;                                    //一战到底

    CAcaCupMgr              m_stAcaCupMgr;                                      //学院杯
    CChatMgr                m_stChatMgr;                                        //聊天

    CMarketMgr              m_stMarketMgr;                                      //任务集市;
    CManorBattleMgr         m_stManorBattleMgr;                                 //领地战
    CRewardBackMgr          m_stRewardBackMgr;                                  //奖励找回
    CLoginRewardMgr         m_stLoginRewardMgr;                                 //登录奖励
};

#endif //__MAINSVR_CTRL_H__
